package main

import (
	"encoding/json"
	"fmt"
	"time"

	//"logmod"
	r "other-backend/redis_config"

	"github.com/garyburd/redigo/redis"
)

const (
	PlaybookTaskQ  string = "playbook_tasks_queue"
	PrePareTaskMap string = "prepare_run_tasks_map"
	PrePareTaskQ   string = "prepare_task_queue"
)

var Pool *redis.Pool
var R2 r.RedisConfig
var Env string = "online"

func Redispool() {
	// 10.8.121.199:6382
	//RedisHost := "10.0.0.31:6379"
	R2 = r.GetRedisConf(Env)
	RedisHost := R2.FullHost
	fmt.Printf("it will connecting %s\n", R2.FullHost)
	//option := redis.DialPassword("ansibleapi")
	option := redis.DialPassword(R2.Passwd)

	Pool = &redis.Pool{
		MaxIdle:     10,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			return redis.Dial("tcp", RedisHost, option)
		},
	}
}

func QueuedKeyCount(key string) (int, error) {
	c := Pool.Get()
	/*
		exist, err := redis.int(c.Do("exists", key))

		if err != nil || exist >= 1 {
			fmt.Printf("the key %v is exists\n", key)
			//return 0, errors.New("could not found redis key")
			fmt.Println(err)
			fmt.Println(exist)
			return 0, err
		}
	*/
	lenqueue, err := redis.Int(c.Do("llen", key))
	if err != nil {
		fmt.Printf("Error:get queue name:%v lens error", key)
		fmt.Println(err)
		return 0, err
	}
	return lenqueue, nil

}

func Lpopdata(key string) (data string, err error) {
	c := Pool.Get()
	data, err = redis.String(c.Do("lpop", key))
	if err != nil {
		fmt.Println(err)
	}
	return data, err
}

func Setdata(key string, value interface{}) (err error) {

	c := Pool.Get()
	_, err = c.Do("set", key, value)
	if err != nil {
		return err
	}
	return nil
}

func Lpushdata(key string, value string) (err error) {
	c := Pool.Get()
	_, err = c.Do("rpush", key, value)
	if err != nil {
		fmt.Println("rpush data error")
		//return errors.New("lpush data error")
		return err
	}
	return nil
}
func Hsetdata(key string, filed string, value string) (err error) {
	c := Pool.Get()
	_, err = c.Do("hset", key, filed, value)
	if err != nil {
		fmt.Println("hset data error")
		//return errors.New("lpush data error")
		return err
	}
	return nil
}

func hexistsFiled(key string, filed string) (data interface{}, err error) {
	c := Pool.Get()
	data, err = c.Do("hexists", key, filed)
	if err != nil {
		fmt.Println("hexistsFiled data error")
		//return errors.New("lpush data error")
		return 0, err
	}
	return data, nil
}

func Getdata(key string) (data int, err error) {
	c := Pool.Get()
	data, err = redis.Int(c.Do("get", key))
	if err != nil {
		return 0, err
	}
	return data, err
}

type Inv struct {
	All struct {
		Hosts []string `json:"hosts"`
		//Host_vars map[string]string `json:"vars"`

		Vars struct {
			TaskId string `json:"task_id"`
		} `json:"vars"`
	} `json:"all"`
}

func GetTasksData(QueueNameKey string, ShutdownStatus string, Tasks chan string, Stopch chan bool) {
	for {
		Num, err := QueuedKeyCount(QueueNameKey)
		if err != nil {
			fmt.Println(err)
		}
		if Num > 0 {
			for Num > 0 {
				data, err := Lpopdata(QueueNameKey)
				fmt.Printf("pop the key from playbook_tasks_queue of web interface is:%v\n", data)
				if err != nil {
					fmt.Println("ERROR:pop key error")
					fmt.Println(err)
					break
				} else {
					Tasks <- data
					Num--
					fmt.Println(Num)
				}
			}

		}
		fmt.Println("Stage:Prepare Task Struct, sleep 2 seconds and waiting for the tasks\n")
		time.Sleep(time.Second * 2)

		Status, err := Getdata(ShutdownStatus)
		if err != nil {
			fmt.Println("Error:get shutdownStatus failed")
		} else {
			if Status == 1 {
				fmt.Println("get shutdown ch eq 1,shutdowning tasks ")
				Stopch <- true
				close(Tasks)
				return
			}
		}

		// get stop key from redis
		//if key > 0 ,Stopch = True
	}
}

func Push_Task_Prepare_TaskQ(jsonstr string) {

	var data Inv
	fmt.Println("enter Unmarshal stage:")
	if err := json.Unmarshal([]byte(jsonstr), &data); err == nil {
		fmt.Println("struct ansible inventory")
		TaskID := data.All.Vars.TaskId
		if TaskID == "" {
			fmt.Printf("error:taskId is empty")
			// sendalert
		}

		//key := "prepare_run_tasks_mapping"

		//这段逻辑有坑，待修复，如果有key输出是1，但线上不知为什么
		data, err := hexistsFiled(PrePareTaskMap, TaskID)
		fmt.Println(data)
		if data == 1 {
			fmt.Println("Error:the key has exist")
			//sendalert
			// exit or break
			fmt.Println(data)
		} else {
			err = Hsetdata(PrePareTaskMap, TaskID, jsonstr)
			if err != nil {
				fmt.Printf("Error:hset %s occur error", TaskID)
				// sendalert
			} else {
				fmt.Printf("Info:has hset %s to queue", TaskID)
				// sendalert
				err := Lpushdata(PrePareTaskQ, TaskID)
				if err != nil {
					fmt.Printf("Error:push prepare id failed")
					//to do alert
				}
			}
		}
	} else {
		fmt.Println("Error:Unmarshal jsonstr to struct failed,the data is incorrect")
	}
}

func main() {
	Redispool()
	defer Pool.Close()

	Tasks := make(chan string)
	Stopch := make(chan bool)
	TaskQueueKey := PlaybookTaskQ
	ShutdownTaskKey := "shutdown_prepare_taskid"
	AnsibleTasks := "x"

	go GetTasksData(TaskQueueKey, ShutdownTaskKey, Tasks, Stopch)
	for {
		select {
		case AnsibleTasks = <-Tasks:
			Push_Task_Prepare_TaskQ(AnsibleTasks)
			//fmt.Println(c)

		case _ = <-Stopch:
			goto end
		}
	}

end:
}
